/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.object;

import java.awt.image.BufferedImage;
import net.worlds.WorldsException;
import net.worlds.Main;
import net.worlds.input.InputState;
import org.jbox2d.common.Vec2D;
import se.krka.kahlua.vm.JavaFunction;
import se.krka.kahlua.vm.LuaCallFrame;


public class Character extends AbstractCharacter{
    public Seat seat = null;
    public Weld seatWeld = null;
    public long leftSeatTime;
    public Tool net_selectedTool = null;
    public boolean net_armRotation = false;
    public double net_armAngle = 0;
    public Character() throws WorldsException
    {
        super("Character");
        addFunction("setSeat", new JavaFunction()
        {

            public int call(LuaCallFrame callFrame, int nArguments) {
                if(nArguments != 2 || !(callFrame.get(1) instanceof Seat))
                    throw new RuntimeException("setSeat() requires a seat argument");
                if(Main.isServer())
                    throw new RuntimeException("This function may only be used in client-side scripts");
                setSeat((Seat) callFrame.get(1));
                return 0;
            }

        });
    }
    public void setSeat(final Seat s)
    {
        if(seat == null && hasChild("Body"))
        {
            Runnable r = new Runnable()
            {
                public void run() {
                    if(seat == null && hasChild("Body"))
                        try {
                            worldLocked = true;
                            GameObject body = getChild("Body");
                            s.setProp("Collidable", false, true);
                            s.getBody().resetFiltering();
                            body.setProp("Rotation", s.getProp("Rotation"), true);
                            Vec2D offset = new Vec2D(0, 4).rotate(s.getBody().getAngle());
                            body.setProp("Position", s.getVec2DProp("Position").add(offset), true);
                            Weld w = (Weld) world.createObject("Weld");
                            w.setProp("Name", "SeatWeld", true);
                            w.setProp("Visible", false, true);
                            w.setProp("Anchor", s.getPosition(), true);
                            w.setProp("Part2", body, true);
                            w.setProp("Part1", s, true);
                            if(body.hasChild("Controller"))
                                body.getChild("Controller").setProp("Velocity", Vec2D.ORIGIN, true);
                            body.setProp("Velocity", Vec2D.ORIGIN, true);
                            if(s.getBooleanProp("Fixed"))
                                body.setProp("Fixed", true, true);
                            else
                                w.setProp("Parent", world.getService("JointsService"), true);
 
                              if(body.hasChild("FixedRotation"))
                                body.getChild("FixedRotation").setProp("Disabled", true, true);                          seatWeld = w;
                            seat = s;
                        } catch (WorldsException ex) {
                            ex.printStackTrace();
                        }
                }
            };
            Main.addStepTask(r);
        }
        else if(s == null && seat != null && hasChild("Body"))
        {
            Runnable r = new Runnable()
            {
                public void run() {
                    if(s == null && seat != null && hasChild("Body"))
                        try {
                            final GameObject body = getChild("Body");
                            if(body.getBooleanProp("Fixed"))
                                body.setProp("Fixed", false, true);
                            else if(seatWeld.inWorld)
                                world.deleteObject(seatWeld);
                            seatWeld = null;
                            seat.setProp("Collidable", true, true);
                            seat.getBody().resetFiltering();
                            seat = null;
                            leftSeatTime = System.currentTimeMillis();
                            body.setProp("Rotation", 0.0f, true);
                            if(body.hasChild("FixedRotation"))
                                body.getChild("FixedRotation").setProp("Disabled", false, true);
                            worldLocked = false;
                        } catch (WorldsException ex) {
                            ex.printStackTrace();
                        }
                }
            };
            Main.addStepTask(r);
        }
    }
    @Override
    protected double getArmAngle() {
        try {
            if(getBooleanProp("OverrideArmRotation"))
                return Math.toRadians(getFloatProp("ArmRotation"));
            else if (isPlayer()) {
                mouseAngle = new Vec2D(InputState.mouseX - armAbsCenter.x, InputState.mouseY - armAbsCenter.y).normalized().toAngle();
                double armAngle = mouseAngle - Math.PI / 2;
                return armAngle;
            } else if (Main.isClient() || Main.isServer()) {
                return net_armAngle;
            } else {
                return 0;
            }
        } catch (WorldsException ex) {
            ex.printStackTrace();
            return 0;
        }
    }

    @Override
    protected BufferedImage getToolTexture() throws WorldsException {
        Tool t = null;
        if(isPlayer())
            t = Main.getLocalPlayer().getSelectedTool();
        else if(Main.isClient() || Main.isServer())
            t = net_selectedTool;
        if(t != null && t.getBooleanProp("Holdable") && t.getTexture() != null)
            return t.getTexture();
        else
            return null;
    }

    @Override
    protected Vec2D getToolOffset() throws WorldsException {
        Tool t = null;
        if(isPlayer())
            t = Main.getLocalPlayer().getSelectedTool();
        else if(Main.isClient() || Main.isServer())
            t = net_selectedTool;
        if(t != null && t.getBooleanProp("Holdable"))
            return t.getVec2DProp("TextureOffset");
        else
            return null;
    }

    protected Vec2D getToolSize() throws WorldsException {
        Tool t = null;
        if(isPlayer())
            t = Main.getLocalPlayer().getSelectedTool();
        else if(Main.isClient() || Main.isServer())
            t = net_selectedTool;
        if(t != null && t.getBooleanProp("Holdable"))
            return t.getVec2DProp("Size");
        else
            return null;
    }

    @Override
    protected boolean armRotationEnabled() throws WorldsException {
       return (getBooleanProp("OverrideArmRotation")) || (isPlayer() && Main.getLocalPlayer() != null && Main.getLocalPlayer().enableArmRotation) || ((Main.isClient() || Main.isServer()) && net_armRotation);
    }
    public boolean isPlayer() throws WorldsException
    {
        return Main.getLocalPlayer() != null && Main.getLocalPlayer().getPlayer().getObjectProp("Character") == this;
    }

    @Override
    protected Vec2D getPositionDifference() {
        try {
            if(isPlayer())
            {
                return new Vec2D(Main.getLocalPlayer().d, 0);
            }
            else if(hasChild("Body") && getChild("Body") instanceof Part)
            {
                Part bodyPart = (Part) getChild("Body");
                return bodyPart.getPosition().sub(bodyPart.getOldPosition());
            }
            else
                return Vec2D.ORIGIN;
        } catch (WorldsException ex) {
            return Vec2D.ORIGIN;
        }
    }

}
